package org.hdl.anima.handler;

import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.hdl.anima.Application;
import org.hdl.anima.message.IMessage;
import org.hdl.anima.utils.XMLFileHelper;

/**
 * 
 * @author qiuhd
 * @since  2014年8月4日
 */
public final class ServiceHanlderHelper {

	private final static String CONF_PATH = "/" ;
	
	private final static String CONF_NAME_STRING = "ServicerHanlders.xml";
	
	private ServiceHanlderHelper() {}
	
	@SuppressWarnings("unchecked")
	public static final Map<Integer, Handler> loadFromStaticXmlInfo(Application app) throws Exception{
		Document document= XMLFileHelper.getXMLFile(CONF_PATH + CONF_NAME_STRING);
		Element root = document.getRootElement();
		Iterator<Element> eleIt =  root.elementIterator();
		
		Map<Integer, Handler> serviceHanlderMap = new HashMap<Integer, Handler>();
		while (eleIt.hasNext()) {
			Element itemEle =  eleIt.next();
			String id = itemEle.attributeValue("id");
			
			if (id == null || "".equals(id)) {
				throw new IllegalArgumentException("Failed to Load " + CONF_NAME_STRING  + ",casuse:the id attribute is empty!");
			}
			
			int hId = 0 ;
			try {
				hId = Integer.valueOf(id);
			}catch (NumberFormatException e) {
				throw new IllegalArgumentException("Failed to Load " + CONF_NAME_STRING  + ",casuse:the id attribute format is not int!");
			}
			
			String clazz = itemEle.attributeValue("class");
			
			if (clazz == null || "".equals(clazz)) {
				throw new IllegalArgumentException("Failed to Failed to  Load " + CONF_NAME_STRING  + ",casuse:the class attribute is empty id :" + id);
			}
			
			Class<?> hClazz;
			try {
				hClazz = Class.forName(clazz);
			} catch (ClassNotFoundException e1) {
				throw new IllegalArgumentException("Failed to Load " + CONF_NAME_STRING  + ",casuse:class not found id :" + id);
			}
			
			if (!Handler.class.isAssignableFrom(hClazz)) {
				throw new IllegalArgumentException("Failed to Load " + CONF_NAME_STRING  + ", casuse:class type not match id :" + id);
			}
			
			Object handler = null;
			try {
				Constructor<?> appCon = null;
				try {
					appCon = hClazz.getConstructor(Application.class);
				}catch (Exception e) {
					//ignore
				}
				
				if (appCon != null) {
					handler = appCon.newInstance(app);
				}else {
					handler = hClazz.newInstance();
				}
				
				if (handler instanceof AbstractServiceHandler) {
					((AbstractServiceHandler<?>) handler).setApplication(app);
				}
			}catch (Exception e) {
				throw new IllegalStateException("Failed to Load " + CONF_NAME_STRING  + ",casuse:class can not instance id :" + id,e);
			}
			
			Handler serviceHandler = (Handler) handler; 
			serviceHanlderMap.put(hId, serviceHandler);
			
			try {
				Type type =  serviceHandler.getClass().getGenericSuperclass();
				if (ParameterizedType.class.isAssignableFrom(type.getClass())) {
					ParameterizedType t = (ParameterizedType) type ;
					Type[] typeArray = t.getActualTypeArguments();
					Class<? extends IMessage> msgClazz = (Class<? extends IMessage>) typeArray[0];
					RequestMessageFactory.getInstance().register(hId,msgClazz);
				}
			} catch (Exception e) {
				throw new IllegalStateException("Failed to get message type from service handler, service handler id:" + hId);
			}
		}
		
		return serviceHanlderMap;
	}
	
	public static final Map<Integer, Handler> loadFromAn() {
		return null;
	}
}

